<?php
/**
 * Block manager component
 * @author Kirill A Egorov kirill.a.egorov@gmail.com 
 * @copyright Copyright (C) 2011-2012  Kirill A Egorov, 
 * DVelum project http://code.google.com/p/dvelum/ , http://dvelum.net
 * @license General Public License version 3
 */
class Blockmanager
{
	protected static $_instance = null;
	protected $_map;
	protected $_pageId;

	const CACHE_KEY = 'blockmanager_data';
	
	protected function __construct(){}
	protected function __clone(){}
	
	/**
	 * @return Blockmanager
	 */
	static public function getInstance()
	{
		if(is_null(self::$_instance))
			self::$_instance = new self();
		return self::$_instance;
	}
	/**
	 * Init block manager, get data
	 * @param string $pageId
	 * @return void
	 */
	public function init($pageId)
	{
		$this->_map = array();
		$this->_pageId = $pageId;
		$this->_loadBlocks();
	}
	/**
	 * Load blocks configs and render blocks
	 * @return void
	 */
	protected function _loadBlocks()
	{	
		$mapData = $this->_loadMap();
		if(empty($mapData))
			return;
			
		$ids = array_unique(Utils::fetchCol('block_id', $mapData));
	
		$blocksData = Model_Blocks::getInstance()->getList(
			false , 
			array('id' => $ids , 'published' => true) , 
			array('id' , 'title' , 'text' , 'is_system' , 'show_title' , 'sys_name')
		);
	
		if(empty($blocksData))
			return;
	
		$blocksData = Utils::rekey('id', $blocksData);
		$blocksData = array_map(array('self','_renderBlock'), $blocksData);

		$this->_map = array();
		foreach ($mapData as $k=>$v)
			if(isset($blocksData[$v['block_id']]))
				$this->_map[$v['place']][] = $blocksData[$v['block_id']];	
	}
	/**
	 * Load Blocks map
	 * @return boolean
	 */
	protected function _loadMap()
	{
		$cache = Application::dataCache();
		$hashKey = self::hashPage($this->_pageId);
		
		if(!$cache || !$data = $cache->load($hashKey))
		{
		    $model = Model_Blockmapping::getInstance();
			$data = $model->getList(
				array('sort' => 'order_no' , 'die' => 'DESC') , 
				array('page_id' => $this->_pageId)
			);
			
			if($cache)
				$cache->save($data , $hashKey);	
		}	
		
		/*
		 * Get default block map
		 */
		if(empty($data))
		{
			$hashKey = self::hashPage(0);
			if(!$cache || !$data = $cache->load($hashKey)){
				$data = $model->getList(
					array('sort' => 'order_no' , 'die' => 'DESC') , 
					array('page_id' => 0)
				);
			}
			if($cache)
				$cache->save($data , $hashKey);
		}
		
		if(empty($data))
			return array();
				
		return $data;
	}
	
	/**
	 * Init and render Block object
	 * @param array $config
	 * @return string
	 */
	static protected function _renderBlock(array $config)
	{
		$class = 'Block_Simple';
		
		if($config['is_system'] && strlen($config['sys_name']) && class_exists($config['sys_name']))
				$class = $config['sys_name'];
		
		$blockObject = new $class($config);
		
		if(!$blockObject instanceof Block_Abstract)
			trigger_error('Invalid block class');
		
		return $blockObject->render();
	}
	/**
	 * Get Blocks Html by place code
	 * @param string $placeCode
	 * @return string
	 */
	public function getBlocksHtml($placeCode){
		if(!isset($this->_map[$placeCode]))
			return '';
	
		return implode("\n", $this->_map[$placeCode]);
	}
	/**
	 * Get cache key for page
	 * @param integer $id
	 * @return string
	 */
	static public function hashPage($id){
		return self::CACHE_KEY.'_'.$id;
	}
}